package com.android.aqq;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import com.android.aqq.bean.BuddyGroup;
import com.android.aqq.bean.ChatState;
import com.android.aqq.bean.QQBuddy;
import com.android.aqq.bean.QQGroup;
import com.android.aqq.bean.QQGroupMember;
import com.android.aqq.bean.SortList;
import com.android.aqq.util.QQEventUtils;
import com.android.aqq.util.Utils;

import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.QQClient;
import edu.tsinghua.lumaqq.qq.Util;
import edu.tsinghua.lumaqq.qq.beans.CardStub;
import edu.tsinghua.lumaqq.qq.beans.ClusterInfo;
import edu.tsinghua.lumaqq.qq.beans.QQFriend;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.events.IQQListener;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.net.PortGateFactory;
import edu.tsinghua.lumaqq.qq.packets.in.ClusterCommandReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetFriendListReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GroupDataOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SystemNotificationPacket;
import edu.tsinghua.lumaqq.qq.packets.in._09.LoginGetListReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.AddFriendAuthResponsePacket;

public class QQService extends Service implements IQQListener{
	private QQClient client = null;
	private QQUser user = null;
	private Handler controlHandler;
	public static boolean hasRemark = true;
	public static int friendsRemarkPage = 0;
	
	private List<BuddyGroup> mGroupData = null;
	private List<SortList<QQBuddy>> mChildData = null;
	private Map<Integer, Integer> mBuddyGroupMap = null;
	public static Map<Integer, ChatState> mChatStates = null;
	private NotificationManager mNotificationManager;
	private Map<Integer, QQBuddy> mBuddyMap = null; //好友QQ号与名称对应Map
	private List<QQGroup> mQQGroups = null;
	private boolean isMute = false;
	private boolean receiveGroupIm = false;
	private SharedPreferences mSharedPref;
	private int loginGetListPosition;
	
	public static boolean hasDataDownloaded; //已经下载数据
	
    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class LocalBinder extends Binder {
        QQService getService() {
            return QQService.this;
        }
    }
    
    @Override
    public void onCreate() {
        //初始化属性
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mChatStates = new HashMap<Integer, ChatState>();
        setForeground(true);
        mSharedPref = PreferenceManager.getDefaultSharedPreferences(QQService.this);
        isMute = mSharedPref.getBoolean("MUTE_LOGIN", false);
        receiveGroupIm = mSharedPref.getBoolean("RECEIVE_GROUP_IM", false);
        
    	if (mBuddyGroupMap == null) {
    		mBuddyGroupMap = new HashMap<Integer, Integer>();
    	}
    	if (mQQGroups == null) {
    		mQQGroups = new ArrayList<QQGroup>();
    	}
    }
    
    public void clear() {
    	if (mChatStates != null) mChatStates.clear();
    	mChildData = null;
    	mGroupData = null;
    	mBuddyGroupMap = null;
    	mBuddyMap = null;
    	mQQGroups = null;
    	hasRemark = true;
    	friendsRemarkPage = 0;
    	hasDataDownloaded = false;
    }
    
	public void startLogin(String account, String password, boolean isHidden) {
        try {
        	if (!Utils.isNetworkAvailable(this)) {
        		controlHandler.sendMessage(Message.obtain(controlHandler, -1, "没有网络连接！"));
        		return;
			}
        	
        	user = new QQUser(Integer.parseInt(account), password);
            if (user.isLoggedIn()) {
            	client.logout();
            }

            Log.d("aQQ", "isHidden = " + isHidden);
            user.setLoginMode(isHidden?QQ.QQ_LOGIN_MODE_HIDDEN:QQ.QQ_LOGIN_MODE_NORMAL);
            user.setStatus(isHidden?QQ.QQ_STATUS_HIDDEN:QQ.QQ_STATUS_ONLINE);
        	
            client = new QQClient();
            client.setConnectionPoolFactory(new PortGateFactory());
            client.addQQListener(this);
            
            // 设置参数
            user.setUdp(true);
            client.setUser(user);
            String server = mSharedPref.getString("server_preference", "sz.tencent.com");
            if (server.equals("自定义")) {
            	server = mSharedPref.getString("customer_server_preference", "sz.tencent.com");
            }
            Log.d("aQQ", "server="+server);
            client.setLoginServer(server);
        	
            // 登录
            client.login();
        } catch (Exception e) {
            e.printStackTrace();
            logout();
            controlHandler.sendMessage(Message.obtain(controlHandler, -1, e.toString()));
        }
	}
	
    
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
        	QQEvent event = (QQEvent) msg.obj;
        	switch(msg.what) {
//        	case QQEvent.SYS_TIMEOUT: //系统超时
        	case QQEvent.LOGIN_UNKNOWN_ERROR: //登录错误
        		logout();
        		
        		sendHandlerMessage(msg);
        		break;
//        	case QQEvent.USER_GET_INFO_OK: //得到用户信息成功
//        		ContactInfo contactInfo = ((GetUserInfoReplyPacket) event.getSource()).contactInfo;
//        		if (contactInfo.qq == user.getQQ()) {
//        			mContactInfo = contactInfo;
//        		} else {
//        			QQBuddy friend = mBuddyMap.get(contactInfo.qq);
//            		if (friend != null) {
//            			friend.setContactInfo(contactInfo);
//            			sendHandlerMessage(msg);
//            		}
//        		}
//        		break;
        	case QQEvent.FRIEND_GET_GROUP_NAMES_OK: //下载分组名称成功，发送LoginGetListPacket
            	processGroup((GroupDataOpReplyPacket) event.getSource());
            	
            	//获取好友和群列表
            	loginGetListPosition = 1;
        		client.loginGetList(0);
            	break;
        	case QQEvent.LOGIN_GET_LIST_OK:
        		LoginGetListReplyPacket lp = (LoginGetListReplyPacket) event.getSource();
    			processLoginGetList(lp);
    			if (lp.hasMore) {
    				client.loginGetList(loginGetListPosition++);
    			} else {
    				//获取好友信息
    				client.getFriendList();
    				
    				if (receiveGroupIm) {
    					//获得群信息
                		getQQGroupsInfo();
    				}
    			}
        		break;
        	case QQEvent.FRIEND_GET_LIST_OK: //获得好友列表成功
            	GetFriendListReplyPacket fp = (GetFriendListReplyPacket) event.getSource();
    			processFriendList(fp);
    			if (fp.position != 0xFFFF) {
    				client.getFriendList(fp.position);
    			} else {
//    				for (int i=0; i<mChildData.size(); i++) {
//    					Collections.sort(mChildData.get(i), Comparators.getComparator());
//    				}
    				sendHandlerMessage(msg);
        			showNotification("已登录");
//        			//获取在线好友列表
//    				client.user_GetOnline();
    				//获取好友备注
    				client.user_GetRemarks(0);
    			}
    			
            	break;
//        	case QQEvent.FRIEND_GET_REMARKS_OK: //得到好友备注
//        		hasRemark = ((FriendDataOpReplyPacket)event.getSource()).hasRemark;
//            	if (hasRemark) {
//            		friendsRemarkPage ++;
//            		client.user_GetRemarks(friendsRemarkPage);
//            	}
//            	sendHandlerMessage(msg);
//        		break;
        	case QQEvent.CLUSTER_GET_INFO_FAIL:
        	case QQEvent.CLUSTER_GET_INFO_OK: //得到群信息成功
        		processClusterInfo((ClusterCommandReplyPacket) event.getSource());
        		break;
        	case QQEvent.CLUSTER_GET_MEMBER_INFO_FAIL:
        		break;
        	case QQEvent.CLUSTER_GET_MEMBER_INFO_OK: //得到群成员信息成功
        		processMemberInfo((ClusterCommandReplyPacket) event.getSource());
        		break;
        	case QQEvent.CLUSTER_GET_CARDS_FAIL:
        		break;
        	case QQEvent.CLUSTER_GET_CARDS_OK: //批量获得群名片成功
        		processGetCardsOK((ClusterCommandReplyPacket) event.getSource());
        		break;
        	case QQEvent.CLUSTER_GET_ONLINE_MEMBER_FAIL:
        		break;
        	case QQEvent.CLUSTER_GET_ONLINE_MEMBER_OK:
        		processGetOnlineMember((ClusterCommandReplyPacket) event.getSource());
        		break;
        	case QQEvent.USER_KEEP_ALIVE_FAIL: //保持连接失败
        		logout();
        		showNotification("未登录");
        		Toast.makeText(QQService.this, "与服务器保持连接失败。", Toast.LENGTH_LONG).show();
        		break;
            case QQEvent.SYS_KICKED: //被系统踢出
            	showNotification("未登录");
            	processSysKicked((ReceiveIMPacket) event.getSource());
            	break;
            case QQEvent.IM_SEND_OK: //消息发送成功
            case QQEvent.USER_KEEP_ALIVE_OK:
            	break;
            case QQEvent.SYS_REQUEST_ADD_EX: 
            	processSysRequestAdd((SystemNotificationPacket) event.getSource());
            	break;
            case QQEvent.FRIEND_AUTH_SEND_OK: //对方加我好友，我通过并加对方好友
            	int qq = ((AddFriendAuthResponsePacket) event.getSource()).getTo();
            	QQBuddy buddy = mBuddyMap.get(qq);
            	if (buddy == null) {
            		buddy = new QQBuddy(qq);
            		mBuddyMap.put(qq, buddy);
            	} 
            	buddy.setVerifyFlag(QQ.QQ_AUTH_ALREADY);
            	client.user_Add(qq);
            	break;
            //错误处理
            case QQEvent.ERROR_CONNECTION_BROKEN:
            case QQEvent.ERROR_NETWORK:
            case QQEvent.ERROR_PROXY:
            case QQEvent.ERROR_RUNTIME:
            	logout();
            	break;
            case QQEvent.IM_CLUSTER_SEND_EX_FAIL:
            	Toast.makeText(QQService.this, QQEventUtils.getQQEventDesc(msg.what, event.getSource()), Toast.LENGTH_LONG).show();
    			break;
        	default:
        		if (controlHandler != null) {
        			sendHandlerMessage(msg);
        		} else {
        			String message = Integer.toHexString(msg.what)  + "：" + QQEventUtils.getQQEventDesc(msg.what, event.getSource());
            		Toast.makeText(QQService.this, message, Toast.LENGTH_LONG).show();
        		}
        		break;
        	}
        }

		private void sendHandlerMessage(Message msg) {
			if (controlHandler != null) {
				Message m = Message.obtain(msg);
				m.setTarget(controlHandler);
				controlHandler.sendMessage(m);
			}
		}

    };
    
    private void processSysKicked(ReceiveIMPacket packet) {
    	logout();
    	Toast.makeText(this, packet.sysMessage, Toast.LENGTH_LONG).show();
	}
    
//    private void processSysRequestAdd(SystemNotificationPacket packet) {
//    	Intent intent = new Intent(QQService.this, QQDialog.class);
//    	intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//    	intent.putExtra("message", packet.message);
//    	intent.putExtra("qq", packet.from);
//    	startActivity(intent);
//	}
    
    private void processFriendList(GetFriendListReplyPacket fp) {
    	List<QQFriend> friends = fp.friends;
    	for (int i=0; i<friends.size(); i++) {
    		QQFriend friend = friends.get(i);
    		
    		QQBuddy bean = mBuddyMap.get(friend.qqNum);
    		if (bean != null) {
    			bean.setFriendInfo(friend);
    		}
    	}
		
	}

	private void processSysRequestAdd(SystemNotificationPacket packet) {
    	int qq = packet.from;
    	String text = packet.message;
    	Intent intent = new Intent(this, QQDialogActivity.class);
    	intent.putExtra("QQ", qq);
    	intent.putExtra("MESSAGE", packet.message);
    	PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        final Notification notification = new Notification(R.drawable.message, text,
        		System.currentTimeMillis());
        notification.setLatestEventInfo(this, qq + "请求加你好友", text, contentIntent);
        if (isMute) {
        	notification.defaults = Notification.DEFAULT_VIBRATE;
        } else {
        	notification.defaults = Notification.DEFAULT_SOUND;
        }
        mNotificationManager.notify(qq, notification);
	}

	private void processGetOnlineMember(ClusterCommandReplyPacket packet) {
    	List<Integer> online = packet.onlineMembers;
    	
    	for (int i=0; i<mQQGroups.size(); i++) {
    		if (mQQGroups.get(i).getClusterId() == packet.clusterId) {
    			QQGroup qqGroup = mQQGroups.get(i);
    			List<QQGroupMember> members = qqGroup.getMembers();
    			for (int j=0; j<online.size(); j++) {
    				QQGroupMember member = qqGroup.getMember(online.get(j));
    				if (member != null){
    					byte originalState = member.getStatus();
    					if (originalState!=QQ.QQ_STATUS_ONLINE) {
    						member.setStatus(QQ.QQ_STATUS_ONLINE);
    						members.remove(member);
    						members.add(member);
    					}
    				}
    					
    			}
    			break;
    		}
    	}
	}

	private synchronized void processGetCardsOK(ClusterCommandReplyPacket packet) {
    	List<CardStub> cards = packet.cardStubs;
    	for (int i=0; i<mQQGroups.size(); i++) {
    		if (mQQGroups.get(i).getClusterId() == packet.clusterId) {
    			QQGroup qqGroup = mQQGroups.get(i);
    			for (int j=0; j<cards.size(); j++) {
    				QQGroupMember member = qqGroup.getMember(cards.get(j).qq);
    				if (member != null)
    					member.setName(cards.get(j).name);
    			}
    			break;
    		}
    	}
    	int next = packet.nextStart;
    	if (next>0) {
    		client.cluster_GetCardBatch(packet.clusterId, next);
    	} 
	}

	//处理群成员信息
    private synchronized void processMemberInfo(ClusterCommandReplyPacket packet) {
    	List<QQFriend> memberInfos = packet.memberInfos;
    	for(int i=0; i<mQQGroups.size();i++) {
    		if (mQQGroups.get(i).getClusterId() == packet.clusterId) {
    			mQQGroups.get(i).setMemberInfos(memberInfos);
    			break;
    		}
    	}
    	
	}

	//处理群信息
    private synchronized void processClusterInfo(ClusterCommandReplyPacket packet) {
		if (packet.replyCode == QQ.QQ_REPLY_OK) {
			for (int i=0; i<mQQGroups.size(); i++) {
				if (mQQGroups.get(i).getClusterId() == packet.clusterId) {
					if (packet.info.status == 3) {
						mQQGroups.get(i).setClusterInfo(packet.info);
					}
					mQQGroups.get(i).initMembers(packet.members);
					client.cluster_GetMemberInfo(packet.clusterId, packet.members); 
					break;
				}
			}
			//还有更多的群成员
			if (packet.hasMore) {
				client.cluster_GetInfo(packet.clusterId, packet.nextStart);
			} else {
				client.cluster_GetCardBatch(packet.clusterId, 0);
				client.cluster_GetOnlineMember(packet.clusterId);
			}
		}
	}
    
	private void getQQGroupsInfo() {
    	int size = mQQGroups.size();
		for (int i=0; i<size; i++) {
			client.cluster_GetInfo(mQQGroups.get(i).getClusterId(), 0);
		}
	}

	protected void logout() {
		if (client == null) return;
		
    	if (user!=null && user.isLoggedIn()) {
    		client.logout();
    	}
    	client.release();
	}
    
    
	//处理好友分组的信息
    private void processGroup(GroupDataOpReplyPacket packet) {
    	List<String> groupNames = packet.groupNames;
    	List<Integer> grouSeqs = packet.groupSeqs;
    	if (mGroupData == null) {
			mGroupData = new ArrayList<BuddyGroup>();
		} else { //清空原分组信息
			mGroupData.clear();
		}
    	BuddyGroup group = new BuddyGroup(0,"我的好友");
		mGroupData.add(group);
		for (int i=0; i<groupNames.size(); i++) {
			mGroupData.add(new BuddyGroup(grouSeqs.get(i), groupNames.get(i)));
		}
		
 	}
    
	//处理分组好友
//    private void processGroupFriend(DownloadGroupFriendReplyPacket packet) {
//    	List<DownloadFriendEntry> friends = packet.friends;
//    	int size = friends.size();
//    	if (mGroupFriends == null) {
//    		mGroupFriends = new HashMap<Integer, Integer>();
//    	}
//    	if (mClusters == null) {
//    		mClusters = new ArrayList<QQCluster>();
//    	}
//    	for (int i=0; i<size; i++) {
//    		DownloadFriendEntry friend = friends.get(i);
//    		if (friend.type == 0x1) {
//    			mGroupFriends.put(friend.qqNum, friend.group);
//    		} else {
//    			mClusters.add(new QQCluster(friend.qqNum));
//    		}
//    		
//    	}
//    	
//	}
    
	/**
	 * 处理LoginGetList
	 * @param packet
	 */
	private void processLoginGetList(LoginGetListReplyPacket packet) {
		List<QQFriend> friends = packet.friends;
		
		if (mBuddyMap == null) {
			mBuddyMap = new HashMap<Integer, QQBuddy>();
		}
		
		if (mGroupData == null) {
			mGroupData = new ArrayList<BuddyGroup>();
			BuddyGroup group = new BuddyGroup(0,"我的好友");
			mGroupData.add(group);
		}
		int grouSize = mGroupData.size();
		
		if (mChildData == null) {
			mChildData = new ArrayList<SortList<QQBuddy>>();
			
			for (int i=0; i<grouSize; i++) {
				SortList<QQBuddy> children = new SortList<QQBuddy>();
				mChildData.add(children);
			}
		}
		
		int groupSize = mGroupData.size();
		for (int i=0; i<friends.size(); i++) {
			QQBuddy buddy = new QQBuddy(friends.get(i));
			int group  = buddy.getGroup();
			mBuddyGroupMap.put(buddy.getQQ(), group);
			
			for (int j=0; j<groupSize; j++) {
				if (mGroupData.get(j).getGroupSeq() == group){
					mChildData.get(j).add(buddy);
					break;
				}
			}
			mBuddyMap.put(buddy.getQQ(), buddy);
		}
		
		if (receiveGroupIm) { //如果接收群消息
			List<ClusterInfo> clusters = packet.clusters;
			for (int i=0; i<clusters.size(); i++) {
				QQGroup qqGroup = new QQGroup(clusters.get(i).clusterId);
				mQQGroups.add(qqGroup);
			}
		}
		
	}

    @Override
    public void onDestroy() {
    	clear();
    	logout();
    	mNotificationManager.cancel(aQQActivity.NOTIFICATION_STATUS);
    	super.onDestroy();
    }

	@Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private final IBinder mBinder = new LocalBinder();

    /**
     * Show a notification while this service is running.
     */
    private void showNotification(String message) {
        CharSequence title = getText(R.string.app_name);
        Notification notification = new Notification(R.drawable.message, title,
                System.currentTimeMillis());
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, LoginActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
        notification.setLatestEventInfo(this, title, message, contentIntent);
        notification.flags = Notification.FLAG_NO_CLEAR;
        mNotificationManager.notify(aQQActivity.NOTIFICATION_STATUS, notification);
    }
    
	public void setControlHandler(Handler handler) {
		controlHandler = handler;
	}
	
	public void downloadFriends() {
		//下载分组名称
		client.user_GetGroupNames();
	}

	public List<BuddyGroup> getGroupData() {
		return mGroupData;
	}

	public List<SortList<QQBuddy>> getChildData() {
		return mChildData;
	}

	public Map<Integer, Integer> getBuddyGroupMap() {
		return mBuddyGroupMap;
	}

	public Map<Integer, QQBuddy> getBuddyMap() {
		return mBuddyMap;
	}

	public QQClient getClient() {
		return client;
	}

	public Map<Integer, ChatState> getChatStates() {
		return mChatStates;
	}

	public QQUser getUser() {
		return user;
	}

	public void setClient(QQClient client) {
		this.client = client;
	}

	public void setUser(QQUser user) {
		this.user = user;
	}

	public void qqEvent(QQEvent e) {
		mHandler.sendMessage(Message.obtain(mHandler, e.type, e));
	}

	public List<QQGroup> getQQGroups() {
		return mQQGroups;
	}

	public void loginRequestVerify(byte[] answerToken, String verifyCode) {
		byte[] code = Util.getBytes(verifyCode);
		
		client.loginRequest(answerToken, code, (byte)0x0);
		
	}
	
}

